{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "48ed79cb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Py3_Jupyter_Nb_Pandas(金融Backtest工具测试)_GF_2024-01-20.ipynb\n",
    "# Create By GF 2024-01-20 17:59"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "708af3e9",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd # -> Pandas Version 1.4.1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "ed538bff",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 全局变量(Global Variable)\n",
    "# ##################################################\n",
    "# Stock Terms Interpretation:\n",
    "# Long Buy   : 买多/多方\n",
    "# Short Sell : 卖空/空方\n",
    "# Hold       : 持仓\n",
    "# Idle       : 空仓\n",
    "# --------------------------------------------------\n",
    "Funds_Rest:float = 1000000.00\n",
    "Stock_Holdings:int = 0\n",
    "Stock_Value:float = 0.00\n",
    "Long_Buy_Price:list = []\n",
    "Short_Sell_Price:list = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "69ee6db8",
   "metadata": {},
   "outputs": [],
   "source": [
    "def Safe_Divide(Divisor:float, Dividend:float) -> float:\n",
    "    \n",
    "    if ((Dividend == 0.0) or (Dividend == None)): # -> 如果分母为 0 或者分母为 None。\n",
    "        return None\n",
    "    else:\n",
    "        Result:float = (Divisor / Dividend)\n",
    "        # ..........................................\n",
    "        return Result\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "def List_Average(Lst:list) -> float:\n",
    "    \n",
    "    Result = (sum(Lst) / len(Lst))\n",
    "    # ----------------------------------------------\n",
    "    return Result\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "def String_is_Integer(String:str) -> bool:\n",
    "\n",
    "    Count:int = 0\n",
    "    # ..............................................\n",
    "    String_Length:int = len(String)\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    for i in range(0, String_Length):\n",
    "        if (String[i] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']):\n",
    "            Count += 1\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    if (Count == String_Length):\n",
    "        return True\n",
    "    else:\n",
    "        return False\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "def String_is_Decimal(String:str) -> bool:\n",
    "\n",
    "    Count:int = 0\n",
    "    # ..............................................\n",
    "    String_Length:int = len(String)\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    for i in range(0, String_Length):\n",
    "        if (String[i] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.']):\n",
    "            Count += 1\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    if (Count == String_Length):\n",
    "        return True\n",
    "    else:\n",
    "        return False\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "# ######################################### FinFunc FinTool ##########################################\n",
    "\n",
    "def FinFunc_FinTool_Backtest_Buy_or_Sell_Lots(Close:float, Min_Lots:int=100, Action_Position:str=\"All\", Rtn:str=\"Tuple\"):\n",
    "    \n",
    "    \"\"\"\n",
    "    [Require] Global Variable:\n",
    "              * Funds_Rest:float\n",
    "              * Stock_Holdings:int\n",
    "              \n",
    "              Function: \n",
    "              * String_is_Integer(String:str) -> bool\n",
    "              * String_is_Decimal(String:str) -> bool\n",
    "\n",
    "    [Explain] 手数(Lots)默认值为 100, 即为 1 手, 通常 100 个数量单位的股票被视为 1 手。\n",
    "    \"\"\"\n",
    "    global Funds_Rest     # -> global 关键字, 用于访问全局变量。\n",
    "    global Stock_Holdings # -> global 关键字, 用于访问全局变量。\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    Buy_Lots:int  = 0\n",
    "    Sell_Lots:int = 0\n",
    "\n",
    "    # ----------------------------------------------\n",
    "    if   (Action_Position.lower() == \"all\"):\n",
    "    \n",
    "        Max_Lots = (Funds_Rest - (Funds_Rest % (Close * Min_Lots))) / Close\n",
    "        # ..........................................\n",
    "        Buy_Lots  = Max_Lots\n",
    "        Sell_Lots = Stock_Holdings\n",
    "        \n",
    "    elif (String_is_Integer(Action_Position) == True) and (int(Action_Position) % Min_Lots == 0):\n",
    "    \n",
    "        Buy_Lots  = int(Action_Position)\n",
    "        Sell_Lots = int(Action_Position)\n",
    "    \n",
    "    elif (String_is_Decimal(Action_Position) == True) and (0 <= float(Action_Position)) and (float(Action_Position) <= 1):\n",
    "    \n",
    "        Max_Lots = (Funds_Rest - (Funds_Rest % (Close * Min_Lots))) / Close\n",
    "        # ..........................................\n",
    "        Buy_Lots  = Max_Lots * float(Action_Position)\n",
    "        Sell_Lots = Stock_Holdings * float(Action_Position)\n",
    "    \n",
    "    else:\n",
    "        \n",
    "        Buy_Lots  = Min_Lots\n",
    "        Sell_Lots = Min_Lots\n",
    "    \n",
    "    # Return Value.\n",
    "    # ----------------------------------------------\n",
    "    if   (Rtn.lower() == \"buy\"):\n",
    "        return Buy_Lots\n",
    "    elif (Rtn.lower() == \"sell\"):\n",
    "        return Sell_Lots\n",
    "    else:\n",
    "        return (Buy_Lots, Sell_Lots)\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "# Finance 函数 - 金融工具(Finance Tools) - 开仓(Open Position) - 多方(Long Buy).\n",
    "def FinFunc_FinTool_Backtest_Open_Position_by_Long_Buy(Close:float, Buy_Lots:int) -> int:\n",
    "    \n",
    "    \"\"\"\n",
    "    [Require] Global Variable:\n",
    "              * Funds_Rest:float\n",
    "              * Stock_Holdings:int\n",
    "              * Stock_Value:float\n",
    "              * Long_Buy_Price:list\n",
    "    \"\"\"\n",
    "    global Funds_Rest     # -> global 关键字, 用于访问全局变量。\n",
    "    global Stock_Holdings # -> global 关键字, 用于访问全局变量。\n",
    "    global Stock_Value    # -> global 关键字, 用于访问全局变量。\n",
    "    global Long_Buy_Price # -> global 关键字, 用于访问全局变量。\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    Skip:int = 0\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    Long_Buy_Price.append(Close)\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    Funds_Spent = (Close * Buy_Lots)\n",
    "    # ..............................................\n",
    "    if (Funds_Rest < Funds_Spent):\n",
    "        Skip = Skip + 1\n",
    "        # ..........................................\n",
    "        return int(0)\n",
    "    else:\n",
    "        Funds_Rest = (Funds_Rest - Funds_Spent)\n",
    "        Stock_Holdings = (Stock_Holdings + Buy_Lots)\n",
    "        Stock_Value = (Close * Stock_Holdings)\n",
    "        # ..........................................\n",
    "        return int(1)\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "# Finance 函数 - 金融工具(Finance Tools) - 开仓(Open Position) - 空方(Short Sell).\n",
    "def FinFunc_FinTool_Backtest_Open_Position_by_Short_Sell(Close:float, Open_Lots:int) -> int:\n",
    "    \n",
    "    \"\"\"\n",
    "    [Require] Global Variable:\n",
    "              * Funds_Rest:float\n",
    "              * Stock_Holdings:int\n",
    "              * Stock_Value:float\n",
    "              * Short_Sell_Price:list\n",
    "    \n",
    "              Function:\n",
    "              * List_Average(Lst:list) -> float\n",
    "    \n",
    "    [Explain] 1. 卖空盈利 = 卖空均价 - 当前价\n",
    "                 Short Sell Profit = Average Short Sell Price - Current Price\n",
    "              \n",
    "              2. 持仓市值(卖空) = 卖空均价 * 持仓数量 + 卖空盈利 * 持仓数量\n",
    "                 Position Market Value (Short Sell) = Average Short Sell Price * Number of Holdings + Short Sell Profit * Number of Holdings\n",
    "    \"\"\"\n",
    "    global Funds_Rest       # -> global 关键字, 用于访问全局变量。\n",
    "    global Stock_Holdings   # -> global 关键字, 用于访问全局变量。\n",
    "    global Stock_Value      # -> global 关键字, 用于访问全局变量。\n",
    "    global Short_Sell_Price # -> global 关键字, 用于访问全局变量。\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    Skip:int = 0\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    Short_Sell_Price.append(Close)\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    Funds_Spent = (Close * Open_Lots)\n",
    "    # ..............................................\n",
    "    if (Funds_Rest < Funds_Spent):\n",
    "        Skip = Skip + 1\n",
    "        # ..........................................\n",
    "        return int(0)\n",
    "    else:\n",
    "        Funds_Rest = (Funds_Rest - Funds_Spent)\n",
    "        Stock_Holdings = (Stock_Holdings + Open_Lots)\n",
    "        Stock_Value = ((List_Average(Short_Sell_Price) + (List_Average(Short_Sell_Price) - Close)) * Stock_Holdings)\n",
    "        # ..........................................\n",
    "        return int(1)\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "# Finance 函数 - 金融工具(Finance Tools) - 平仓(Close Position) - 多方(Long Buy).\n",
    "def FinFunc_FinTool_Backtest_Close_Position_by_Long_Buy(Close:float, Sell_Lots:int) -> int:\n",
    "    \n",
    "    \"\"\"\n",
    "    [Require] Global Variable:\n",
    "              * Funds_Rest:float\n",
    "              * Stock_Holdings:int\n",
    "              * Stock_Value:float\n",
    "              * Long_Buy_Price:list\n",
    "    \"\"\"\n",
    "    global Funds_Rest     # -> global 关键字, 用于访问全局变量。\n",
    "    global Stock_Holdings # -> global 关键字, 用于访问全局变量。\n",
    "    global Stock_Value    # -> global 关键字, 用于访问全局变量。\n",
    "    global Long_Buy_Price # -> global 关键字, 用于访问全局变量。\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    Skip:int = 0\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    Funds_Income = (Close * Sell_Lots)\n",
    "    # ..............................................\n",
    "    if (Stock_Holdings < Sell_Lots):\n",
    "        Skip = Skip + 1\n",
    "        # ..........................................\n",
    "        return int(0)\n",
    "    else:\n",
    "        # ..........................................\n",
    "        Funds_Rest = (Funds_Rest + Funds_Income)\n",
    "        Stock_Holdings = (Stock_Holdings - Sell_Lots)\n",
    "        Stock_Value = (Close * Stock_Holdings)\n",
    "        # ..........................................\n",
    "        if (Stock_Holdings == 0):\n",
    "            Long_Buy_Price.clear()\n",
    "        # ..........................................\n",
    "        return int(1)\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "# Finance 函数 - 金融工具(Finance Tools) - 平仓(Open Position) - 空方(Short Sell).\n",
    "def FinFunc_FinTool_Backtest_Close_Position_by_Short_Sell(Close:float, Close_Lots:int) -> int:\n",
    "    \n",
    "    \"\"\"\n",
    "    [Require] Global Variable:\n",
    "              * Funds_Rest:float\n",
    "              * Stock_Holdings:int\n",
    "              * Stock_Value:float\n",
    "              * Short_Sell_Price:list\n",
    "    \n",
    "              Function:\n",
    "              * List_Average(Lst:list) -> float\n",
    "    \n",
    "    [Explain] 1. 卖空盈利 = 卖空均价 - 当前价\n",
    "                 Short Sell Profit = Average Short Sell Price - Current Price\n",
    "              \n",
    "              2. 持仓市值(卖空) = 卖空均价 * 持仓数量 + 卖空盈利 * 持仓数量\n",
    "                 Position Market Value (Short Sell) = Average Short Sell Price * Number of Holdings + Short Sell Profit * Number of Holdings\n",
    "    \"\"\"\n",
    "    global Funds_Rest       # -> global 关键字, 用于访问全局变量。\n",
    "    global Stock_Holdings   # -> global 关键字, 用于访问全局变量。\n",
    "    global Stock_Value      # -> global 关键字, 用于访问全局变量。\n",
    "    global Short_Sell_Price # -> global 关键字, 用于访问全局变量。\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    Skip:int = 0\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    if ((Stock_Holdings < Close_Lots) or (len(Short_Sell_Price) == 0)):\n",
    "        Skip = Skip + 1\n",
    "        # ..........................................\n",
    "        return int(0)\n",
    "    else:\n",
    "        # 买平后[闲置资金] = [闲置资金] + [卖空均价] * [买平手数] + ([卖空均价] - [当前价]) * [买平手数]\n",
    "        # ..........................................\n",
    "        Funds_Rest = (Funds_Rest + ((List_Average(Short_Sell_Price) * Close_Lots) + (List_Average(Short_Sell_Price) - Close) * Close_Lots))\n",
    "        Stock_Holdings = (Stock_Holdings - Close_Lots)\n",
    "        Stock_Value = ((List_Average(Short_Sell_Price) + (List_Average(Short_Sell_Price) - Close)) * Stock_Holdings)\n",
    "        # ..........................................\n",
    "        if (Stock_Holdings == 0):\n",
    "            Short_Sell_Price.clear()\n",
    "        # ..........................................\n",
    "        return int(1)\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "# Finance 函数 - 金融工具(Finance Tools) - 止盈(Stop Profit) - 多方(Long Buy).\n",
    "def FinFunc_FinTool_Backtest_Stop_Profit_by_Long_Buy(Close:float, Sell_Lots:int, Stop_Profit:str=\"Null\") -> int:\n",
    "    \n",
    "    \"\"\"\n",
    "    [Require] Global Variable:\n",
    "              * Long_Buy_Price:list\n",
    "    \n",
    "              Function:\n",
    "              * List_Average(Lst:list) -> float\n",
    "              * FinFunc_FinTool_Backtest_Close_Position_by_Long_Buy(Close:float, Sell_Lots:int) -> int\n",
    "    \n",
    "    [Explain] FinFunc_FinTool_Backtest_Stop_Profit_by_Long_Buy(Close:float, Sell_Lots:int, Stop_Profit:str=\"NULL\") -> int\n",
    "              * Stop_Profit = \"NULL\"        : 什么也不做 (Nothing).\n",
    "              * Stop_Profit = \"percent:0.2\" : 按盈利率止盈, 盈利率达到 20% (Stop Profit by Profit Margin, With a Profit Margin of 20%).\n",
    "              * Stop_Profit = \"price:150\"   : 按价格止盈, 价格达到 150 (Stop Profit Based on Price, Price Reaches 150).\n",
    "    \"\"\"\n",
    "    global Long_Buy_Price\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    Method_and_Numerical:list = []\n",
    "    Method:str = str('')\n",
    "    Numerical:float = float(0.0)\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    if (Stop_Profit.lower() != str(\"null\")):\n",
    "        Method_and_Numerical:list = Stop_Profit.split(':')\n",
    "        # ..........................................\n",
    "        Method:str      = str(Method_and_Numerical[0])\n",
    "        Numerical:float = float(Method_and_Numerical[1])\n",
    "    \n",
    "    # 止盈动作 (Stop Profit Action)。\n",
    "    # ----------------------------------------------\n",
    "    if   (len(Long_Buy_Price) != 0) and ((\"percent\" in Method.lower()) or (\"pct\" in Method.lower())):\n",
    "        \n",
    "        if ((Close - List_Average(Long_Buy_Price)) / List_Average(Long_Buy_Price) >= Numerical):\n",
    "            \n",
    "            # Calling Other Function.\n",
    "            # ......................................\n",
    "            FinFunc_FinTool_Backtest_Close_Position_by_Long_Buy(Close=Close, Sell_Lots=Sell_Lots)\n",
    "            # ......................................\n",
    "            return int(1)\n",
    "        \n",
    "    elif (len(Long_Buy_Price) != 0) and ((\"price\" in Method.lower()) or (\"pc\" in Method.lower())):\n",
    "            \n",
    "        if (Close >= Numerical):\n",
    "            \n",
    "            # Calling Other Function.\n",
    "            # ......................................\n",
    "            FinFunc_FinTool_Backtest_Close_Position_by_Long_Buy(Close=Close, Sell_Lots=Sell_Lots)\n",
    "            # ......................................\n",
    "            return int(1)\n",
    "    else:\n",
    "        \n",
    "        return int(0)\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "# Finance 函数 - 金融工具(Finance Tools) - 止损(Stop Loss) - 多方(Long Buy).\n",
    "def FinFunc_FinTool_Backtest_Stop_Loss_by_Long_Buy(Close:float, Sell_Lots:int, Stop_Profit:str=\"Null\") -> int:\n",
    "    \n",
    "    \"\"\"\n",
    "    [Require] Global Variable:\n",
    "              * Long_Buy_Price:list\n",
    "    \n",
    "              Function:\n",
    "              * List_Average(Lst:list) -> float\n",
    "              * FinFunc_FinTool_Backtest_Close_Position_by_Long_Buy(Close:float, Sell_Lots:int) -> int\n",
    "    \n",
    "    [Explain] FinFunc_FinTool_Backtest_Stop_Profit_by_Long_Buy(Close:float, Sell_Lots:int, Stop_Profit:str=\"NULL\") -> int\n",
    "              * Stop_Profit = \"NULL\"        : 什么也不做 (Nothing).\n",
    "              * Stop_Profit = \"percent:-0.2\" : 按损失率止损, 损失率达到 -20% (Stop Loss by Loss Rate, With a Loss Rate of -20%).\n",
    "              * Stop_Profit = \"price:110\"   : 按价格止损, 价格达到 110 (Stop Loss Based on Price, Price Reaches 110).\n",
    "    \"\"\"\n",
    "    global Long_Buy_Price\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    Method_and_Numerical:list = []\n",
    "    Method:str = str('')\n",
    "    Numerical:float = float(0.0)\n",
    "    \n",
    "    # ----------------------------------------------\n",
    "    if (Stop_Profit.lower() != str(\"null\")):\n",
    "        Method_and_Numerical:list = Stop_Profit.split(':')\n",
    "        # ..........................................\n",
    "        Method:str      = str(Method_and_Numerical[0])\n",
    "        Numerical:float = float(Method_and_Numerical[1])\n",
    "    \n",
    "    # 止损动作 (Stop Loss Action)。\n",
    "    # ----------------------------------------------\n",
    "    if   (len(Long_Buy_Price) != 0) and ((\"percent\" in Method.lower()) or (\"pct\" in Method.lower())):\n",
    "        \n",
    "        if ((Close - List_Average(Long_Buy_Price)) / List_Average(Long_Buy_Price) <= Numerical):\n",
    "            \n",
    "            # Calling Other Function.\n",
    "            # ......................................\n",
    "            FinFunc_FinTool_Backtest_Close_Position_by_Long_Buy(Close=Close, Sell_Lots=Sell_Lots)\n",
    "            # ......................................\n",
    "            return int(1)\n",
    "        \n",
    "    elif (len(Long_Buy_Price) != 0) and ((\"price\" in Method.lower()) or (\"pc\" in Method.lower())):\n",
    "            \n",
    "        if (Close <= Numerical):\n",
    "            \n",
    "            # Calling Other Function.\n",
    "            # ......................................\n",
    "            FinFunc_FinTool_Backtest_Close_Position_by_Long_Buy(Close=Close, Sell_Lots=Sell_Lots)\n",
    "            # ......................................\n",
    "            return int(1)\n",
    "    else:\n",
    "        \n",
    "        return int(0)\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "# ######################################### MapFunc FinTool ##########################################\n",
    "\n",
    "def MapFunc_FinTool_Backtest_Signal(*args, How=\"All\") -> int:\n",
    "    \n",
    "    \"\"\"\n",
    "    [Explain] >>> def ExpFunc_Demo1(*args):\n",
    "                      \n",
    "                      print(args)\n",
    "\n",
    "              >>> def ExpFunc_Demo2(tuple):\n",
    "              \n",
    "                      print(tuple)\n",
    "              \n",
    "              >>> ExpFunc_Demo1(1, 2, 3)\n",
    "              (1, 2, 3)\n",
    "              \n",
    "              >>> ExpFunc_Demo2(tuple=(1, 2, 3))\n",
    "              (1, 2, 3)\n",
    "              \n",
    "              若 args 前面不加 * 则 ExpFunc_Demo1 只能接收一个参数, 参数多给或少给都会报错。\n",
    "              若 args 前面加上 * 则 ExpFunc_Demo1 把接收到的多个参数打包成了一个元组(Tuple), 并赋值给 args 形参。\n",
    "    \"\"\"\n",
    "    Count:int = 0\n",
    "    # ----------------------------------------------\n",
    "    for Idx in range(0, len(args)):\n",
    "        if (args[Idx] == True):\n",
    "            Count += 1\n",
    "    # ----------------------------------------------\n",
    "    if   ((How.lower() == \"all\") and (Count == len(args))):\n",
    "        return int(1)\n",
    "    elif ((How.lower() == \"any\") and (Count >= int(1))):\n",
    "        return int(1)\n",
    "    else:\n",
    "        return int(0)\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "# Map 函数 - 金融工具(Finance Tools) - 回测(Backtesting) - 实时资产 (买多)。\n",
    "def MapFunc_FinTool_Backtest_Real_Time_Asset_by_Long_Buy(\n",
    "        Sig_Buy:int, Sig_Sell:int, Close:float, Act_Posi:str=\"ALL\", Stop_Profit:str=\"Null\", Stop_Loss:str=\"Null\", Rtn:str=\"Tuple\"):\n",
    "    \n",
    "    \"\"\"\n",
    "    [Require] Function:\n",
    "              * FinFunc_FinTool_Backtest_Buy_or_Sell_Lots(Close:float, Min_Lots:int=100, Action_Position:str=\"All\", Rtn:str=\"Tuple\")\n",
    "              * FinFunc_FinTool_Backtest_Open_Position_by_Long_Buy(Close:float, Buy_Lots:int) -> int\n",
    "              * FinFunc_FinTool_Backtest_Close_Position_by_Long_Buy(Close:float, Sell_Lots:int) -> int\n",
    "              * FinFunc_FinTool_Backtest_Stop_Profit_by_Long_Buy(Close:float, Sell_Lots:int, Stop_Profit:str=\"Null\") -> int\n",
    "              * FinFunc_FinTool_Backtest_Stop_Loss_by_Long_Buy(Close:float, Sell_Lots:int, Stop_Profit:str=\"Null\") -> int\n",
    "    \"\"\"\n",
    "    Skip:int = 0\n",
    "    \n",
    "    # Calling Other Function.\n",
    "    # ----------------------------------------------\n",
    "    Buy_Lots:int  = FinFunc_FinTool_Backtest_Buy_or_Sell_Lots(Close=Close, Min_Lots=100, Action_Position=Act_Posi, Rtn=\"Buy\")\n",
    "    Sell_Lots:int = FinFunc_FinTool_Backtest_Buy_or_Sell_Lots(Close=Close, Min_Lots=100, Action_Position=Act_Posi, Rtn=\"Sell\")\n",
    "    \n",
    "    # Calling Other Function.\n",
    "    # ----------------------------------------------\n",
    "    Stop_Profit_Status:int = FinFunc_FinTool_Backtest_Stop_Profit_by_Long_Buy(Close=Close, Sell_Lots=Sell_Lots, Stop_Profit=Stop_Profit)\n",
    "    Stop_Loss_Status:int   = FinFunc_FinTool_Backtest_Stop_Profit_by_Long_Buy(Close=Close, Sell_Lots=Sell_Lots, Stop_Profit=Stop_Loss)\n",
    "    \n",
    "    # 买卖动作 (Buying and Selling Actions)。\n",
    "    # ----------------------------------------------\n",
    "    if   ((Sig_Buy == 1) and (Sig_Sell == 0) and (Stop_Profit_Status == 0) and (Stop_Loss_Status == 0)): # -> 买入做多信号。\n",
    "        \n",
    "        # Calling Other Function.\n",
    "        # ..........................................\n",
    "        FinFunc_FinTool_Backtest_Open_Position_by_Long_Buy(Close=Close, Buy_Lots=Buy_Lots)\n",
    "    \n",
    "    elif ((Sig_Buy == 0) and (Sig_Sell == 1) and (Stop_Profit_Status == 0) and (Stop_Loss_Status == 0)): # -> 卖出平仓信号.\n",
    "        \n",
    "        # Calling Other Function.\n",
    "        # ..........................................\n",
    "        FinFunc_FinTool_Backtest_Close_Position_by_Long_Buy(Close=Close, Sell_Lots=Sell_Lots)\n",
    "    \n",
    "    else:\n",
    "        \n",
    "        Skip = Skip + 1\n",
    "    \n",
    "    # Return Value.\n",
    "    # ----------------------------------------------\n",
    "    if   (Rtn.lower() == \"funds_rest\"):\n",
    "        return Funds_Rest\n",
    "    elif (Rtn.lower() == \"stock_holdings\"):\n",
    "        return Stock_Holdings\n",
    "    elif (Rtn.lower() == \"stock_value\"):\n",
    "        return Stock_Value\n",
    "    else:\n",
    "        return (Funds_Rest, Stock_Holdings, Stock_Value)\n",
    "    # ##############################################\n",
    "    # End of Function.\n",
    "\n",
    "# Map 函数 - 金融工具(Finance Tools) - 回测(Backtesting) - 实时资产 (卖空)。\n",
    "def MapFunc_FinTool_Backtest_Real_Time_Asset_by_Short_Sell(\n",
    "        Sig_Buy:int, Sig_Sell:int, Close:float, Act_Posi:str=\"All\", Rtn:str=\"Tuple\"):\n",
    "    \n",
    "    \"\"\"\n",
    "    [Require] Function:\n",
    "              * FinFunc_FinTool_Backtest_Buy_or_Sell_Lots(Close:float, Min_Lots:int=100, Action_Position:str=\"All\", Rtn:str=\"Tuple\")\n",
    "              * FinFunc_FinTool_Backtest_Open_Position_by_Short_Sell(Close:float, Buy_Lots:int) -> int\n",
    "              * FinFunc_FinTool_Backtest_Close_Position_by_Short_Sell(Close:float, Sell_Lots:int) -> int\n",
    "    \"\"\"\n",
    "    Skip:int = 0\n",
    "    \n",
    "    # Calling Other Function.\n",
    "    # ----------------------------------------------\n",
    "    Open_Lots:int  = FinFunc_FinTool_Backtest_Buy_or_Sell_Lots(Close=Close, Min_Lots=100, Action_Position=Act_Posi, Rtn=\"Buy\")\n",
    "    Close_Lots:int = FinFunc_FinTool_Backtest_Buy_or_Sell_Lots(Close=Close, Min_Lots=100, Action_Position=Act_Posi, Rtn=\"Sell\")\n",
    "\n",
    "    # ----------------------------------------------\n",
    "    if   (Sig_Buy == 0 and Sig_Sell == 1): # -> 卖出做空信号。\n",
    "        \n",
    "        # Calling Other Function.\n",
    "        # ..........................................\n",
    "        FinFunc_FinTool_Backtest_Open_Position_by_Short_Sell(Close=Close, Open_Lots=Open_Lots)\n",
    "    \n",
    "    elif (Sig_Buy == 1 and Sig_Sell == 0): # -> 买入平仓信号。\n",
    "        \n",
    "        # Calling Other Function.\n",
    "        # ..........................................\n",
    "        FinFunc_FinTool_Backtest_Close_Position_by_Short_Sell(Close=Close, Close_Lots=Close_Lots)\n",
    "    \n",
    "    else:\n",
    "        \n",
    "        Skip = Skip + 1\n",
    "    \n",
    "    # Return Value.\n",
    "    # ----------------------------------------------\n",
    "    if   (Rtn.lower() == \"funds_rest\"):\n",
    "        return Funds_Rest\n",
    "    elif (Rtn.lower() == \"stock_holdings\"):\n",
    "        return Stock_Holdings\n",
    "    elif (Rtn.lower() == \"stock_value\"):\n",
    "        return Stock_Value\n",
    "    else:\n",
    "        return (Funds_Rest, Stock_Holdings, Stock_Value)\n",
    "    # ##############################################\n",
    "    # End of Function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "48236353",
   "metadata": {},
   "outputs": [],
   "source": [
    "# ########################################## Long Buy Test ###########################################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "37dea657",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 初始化全局变量(Initial Global Variable)\n",
    "# ##################################################\n",
    "Funds_Rest:float = 1000000.00\n",
    "Stock_Holdings:int = 0\n",
    "Stock_Value:float = 0.00\n",
    "Long_Buy_Price:list = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4ce5b909",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0]剩余资金: 990000.00 / [1]持仓数量: 100 / [2]持仓市值: 10000.00\n"
     ]
    }
   ],
   "source": [
    "# 买入测试: 买入 1 手。\n",
    "# --------------------------------------------------\n",
    "Res = MapFunc_FinTool_Backtest_Real_Time_Asset_by_Long_Buy(Sig_Buy=1, Sig_Sell=0, Close=100, Act_Posi=\"100\")\n",
    "# ..................................................\n",
    "print(\"[0]剩余资金: %.2f / [1]持仓数量: %d / [2]持仓市值: %.2f\" % (Res[0], Res[1], Res[2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "1428044f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0]剩余资金: 495000.00 / [1]持仓数量: 4600 / [2]持仓市值: 506000.00\n"
     ]
    }
   ],
   "source": [
    "# 买入测试: 买入 0.5 倍资金仓位。\n",
    "# --------------------------------------------------\n",
    "Res = MapFunc_FinTool_Backtest_Real_Time_Asset_by_Long_Buy(Sig_Buy=1, Sig_Sell=0, Close=110, Act_Posi=\"0.5\")\n",
    "# ..................................................\n",
    "print(\"[0]剩余资金: %.2f / [1]持仓数量: %d / [2]持仓市值: %.2f\" % (Res[0], Res[1], Res[2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "47776645",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0]剩余资金: 3000.00 / [1]持仓数量: 8700 / [2]持仓市值: 1044000.00\n"
     ]
    }
   ],
   "source": [
    "# 买入测试: 全仓买入。\n",
    "# --------------------------------------------------\n",
    "Res = MapFunc_FinTool_Backtest_Real_Time_Asset_by_Long_Buy(Sig_Buy=1, Sig_Sell=0, Close=120)\n",
    "# ..................................................\n",
    "print(\"[0]剩余资金: %.2f / [1]持仓数量: %d / [2]持仓市值: %.2f\" % (Res[0], Res[1], Res[2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ceee7ba8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0]剩余资金: 342300.00 / [1]持仓数量: 6090 / [2]持仓市值: 791700.00\n"
     ]
    }
   ],
   "source": [
    "# 卖出测试: 卖出 0.3 倍持有仓位。\n",
    "# --------------------------------------------------\n",
    "Res = MapFunc_FinTool_Backtest_Real_Time_Asset_by_Long_Buy(Sig_Buy=0, Sig_Sell=1, Close=130, Act_Posi=\"0.3\")\n",
    "# ..................................................\n",
    "print(\"[0]剩余资金: %.2f / [1]持仓数量: %d / [2]持仓市值: %.2f\" % (Res[0], Res[1], Res[2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "5b47120d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0]剩余资金: 482300.00 / [1]持仓数量: 5090 / [2]持仓市值: 712600.00\n"
     ]
    }
   ],
   "source": [
    "# 止盈测试: 按盈利率达到 0.2 (20%) 止盈 10 手仓位 (盈利率止盈)。\n",
    "# --------------------------------------------------\n",
    "Res = MapFunc_FinTool_Backtest_Real_Time_Asset_by_Long_Buy(Sig_Buy=1, Sig_Sell=0, Close=140, Act_Posi=\"1000\", Stop_Profit=\"pct:0.2\")\n",
    "# ..................................................\n",
    "print(\"[0]剩余资金: %.2f / [1]持仓数量: %d / [2]持仓市值: %.2f\" % (Res[0], Res[1], Res[2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "e5afe8fd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0]剩余资金: 1245800.00 / [1]持仓数量: 0 / [2]持仓市值: 0.00\n"
     ]
    }
   ],
   "source": [
    "# 止盈测试: 按价格达到 150 止盈全部仓位 (限价止盈)。\n",
    "# --------------------------------------------------\n",
    "Res = MapFunc_FinTool_Backtest_Real_Time_Asset_by_Long_Buy(Sig_Buy=1, Sig_Sell=0, Close=150, Stop_Profit=\"PC:150\")\n",
    "# ..................................................\n",
    "print(\"[0]剩余资金: %.2f / [1]持仓数量: %d / [2]持仓市值: %.2f\" % (Res[0], Res[1], Res[2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "f83cecd8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0]剩余资金: 1241800.00 / [1]持仓数量: 0 / [2]持仓市值: 0.00\n"
     ]
    }
   ],
   "source": [
    "# 止损测试: 按价格达到 110 止损全部仓位 (限价止损)。\n",
    "# --------------------------------------------------\n",
    "Res = MapFunc_FinTool_Backtest_Real_Time_Asset_by_Long_Buy(Sig_Buy=1, Sig_Sell=0, Close=150, Act_Posi=\"100\")\n",
    "# ..................................................\n",
    "Res = MapFunc_FinTool_Backtest_Real_Time_Asset_by_Long_Buy(Sig_Buy=1, Sig_Sell=0, Close=110, Stop_Profit=\"price:110\")\n",
    "# ..................................................\n",
    "print(\"[0]剩余资金: %.2f / [1]持仓数量: %d / [2]持仓市值: %.2f\" % (Res[0], Res[1], Res[2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "04439e7b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# ######################################### Short Sell Test ##########################################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "dd477bdb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 初始化全局变量(Initial Global Variable)\n",
    "# ##################################################\n",
    "Funds_Rest:float = 1000000.00\n",
    "Stock_Holdings:int = 0\n",
    "Stock_Value:float = 0.00\n",
    "Short_Sell_Price:list = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "d2758b43",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0]剩余资金: 985000.00 / [1]持仓数量: 100 / [2]持仓市值: 15000.00\n"
     ]
    }
   ],
   "source": [
    "# 卖开测试: 以 150 的价格, 卖开 1 手。\n",
    "# --------------------------------------------------\n",
    "Res = MapFunc_FinTool_Backtest_Real_Time_Asset_by_Short_Sell(Sig_Buy=0, Sig_Sell=1, Close=150, Act_Posi=\"100\")\n",
    "# ..................................................\n",
    "print(\"[0]剩余资金: %.2f / [1]持仓数量: %d / [2]持仓市值: %.2f\" % (Res[0], Res[1], Res[2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "81033b82",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0]剩余资金: 965000.00 / [1]持仓数量: 200 / [2]持仓市值: 30000.00\n"
     ]
    }
   ],
   "source": [
    "# 卖开测试: 以 200 的价格, 卖开 1 手。\n",
    "# --------------------------------------------------\n",
    "Res = MapFunc_FinTool_Backtest_Real_Time_Asset_by_Short_Sell(Sig_Buy=0, Sig_Sell=1, Close=200, Act_Posi=\"100\")\n",
    "# ..................................................\n",
    "print(\"[0]剩余资金: %.2f / [1]持仓数量: %d / [2]持仓市值: %.2f\" % (Res[0], Res[1], Res[2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "a7070365",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0]剩余资金: 990000.00 / [1]持仓数量: 100 / [2]持仓市值: 25000.00\n"
     ]
    }
   ],
   "source": [
    "# 卖开测试: 以 100 的价格, 买平 0.5 倍持有仓位。\n",
    "# --------------------------------------------------\n",
    "Res = MapFunc_FinTool_Backtest_Real_Time_Asset_by_Short_Sell(Sig_Buy=1, Sig_Sell=0, Close=100, Act_Posi=\"0.5\")\n",
    "# ..................................................\n",
    "print(\"[0]剩余资金: %.2f / [1]持仓数量: %d / [2]持仓市值: %.2f\" % (Res[0], Res[1], Res[2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "f33eb025",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0]剩余资金: 1015000.00 / [1]持仓数量: 0 / [2]持仓市值: 0.00\n"
     ]
    }
   ],
   "source": [
    "# 卖开测试: 以 100 的价格, 全仓买平。\n",
    "# --------------------------------------------------\n",
    "Res = MapFunc_FinTool_Backtest_Real_Time_Asset_by_Short_Sell(Sig_Buy=1, Sig_Sell=0, Close=100)\n",
    "# ..................................................\n",
    "print(\"[0]剩余资金: %.2f / [1]持仓数量: %d / [2]持仓市值: %.2f\" % (Res[0], Res[1], Res[2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d9bf6fe0",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
